8.3 Eine Klasse für den Excel-Zugriff
 
Nun ist der Name der Excel-Datei sichergestellt, die Datei existiert. Im zweiten Schritt wird eine Klasse clsExcel erstellt, mit deren Hilfe alle vorkommenden Namen der Statistik ausgelesen werden. Zuerst muss man sich Gedanken über den Ablauf des Programms und die dazu benötigten Eigenschaften und Methoden machen. Die erste Programmieraufgabe ist die Deklaration der Variablen, die mehrmals verwendet werden:
Imports System.IO
Public Class clsExcel
Dim m_xlDateiname As String
Dim m_xlApp As Excel.Application
Dim m_xlMappe As Excel.Workbook
Dim m_xlBlatt As Excel.Worksheet
Dim m_xlZelle As Excel.Range
Schließlich benötigt man eine Eigenschaft, die den Dateinamen von Excel speichert. Sie muss ihn lesen und schreiben können.
Property ExcelDateiName() As String
Get
Return m_xlDateiname
End Get
Set(ByVal Value As String)
m_xlDateiname = Value
End Set
End Property
Damit wird auch der Sinn der global deklarierten Variablen m_xlDateiname deutlich. Nun ist der Name der Mappe bekannt. Sie kann geöffnet werden. Über einen Parameter gibt der Benutzer den Namen einer Zelle an, in welcher die Namen stehen.
Sub Zellzugriff(ByVal Zellname As String)
Try
Dim intZeilen As Integer
Dim strExcelDateiName As String
m_xlApp = New Excel.Application()
m_xlApp.Visible = False
m_xlMappe = m_xlApp.Workbooks.Open(ExcelDateiName)
m_xlBlatt = m_xlMappe.Worksheets(1)
m_xlZelle = m_xlBlatt.Range(Zellname)
Catch ex As IOException
MessageBox.Show(ex.Message)
Catch ex As FileNotFoundException
MessageBox.Show("so nicht!")
MessageBox.Show(ex.Message)
Exit Sub
End Try
End Sub
Die zentrale Rolle spielt nun die Objektvariable m_xlZelle. Mit ihr kann nun weitergearbeitet werden. Man kann die zugehörige Spalte sortieren. Wenn Sie den entsprechenden Befehl nicht kennen oder sich über die Syntax nicht im Klaren sind, dann verwenden Sie den Makrorekorder.
Abbildung 8.6
Der Makrorekorder zeichnet in Excel den Sortierbefehl auf.
Dort findet sich dann beispielsweise der Befehl
Selection.Sort Key1:=("C1"), Order1:=xlAcending, _
Header:=xlGuess, OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom
Dieser Befehl muss noch etwas modifiziert werden, damit er verwendet werden kann.
Sub Sortiere()
m_xlZelle.CurrentRegion.Sort(m_xlZelle, _
Excel.XlSortOrder.xlAscending, _
, , , , , Excel.XlYesNoGuess.xlYes)
End Sub
Die Anzahl der Zeilen wird mit Hilfe einer Eigenschaft angezeigt:
Function ZellwertUnter(ByVal Zeilen As Integer) As String
Return m_xlZelle.Offset(Zeilen, 0).Value()
End Function
Danach läuft ein Zähler vom ersten bis zum letzten Datensatz. Befinden sich zwei gleiche Namen übereinander, so handelt es sich um dieselbe Person.
ReadOnly Property Zeilenzahl()
Get
Return m_xlZelle.CurrentRegion.Rows.Count
End Get
End Property
Zum Schluss wird noch eine Methode benötigt, mit deren Hilfe Excel geschlossen wird. Genauer: Die Datei wird ohne zu speichern geschlossen, die Applikation beendet und die Objektvariablen werden geleert:
Sub ExcelSchließen(ByVal Speichern As Boolean)
m_xlMappe.Close(Speichern)
m_xlApp.Quit()
m_xlZelle = Nothing
m_xlBlatt = Nothing
m_xlMappe = Nothing
m_xlApp = Nothing
End Sub
Beachten Sie, wenn Sie dieses Beispiel in Excel ausprobieren möchten, dass dort der Objektzugriff mit dem Schlüsselwort Set funktioniert. VB.NET hilft, indem auch von den eingebundenen Objekten die Parameter angezeigt werden. Mehr noch: Die Systemkonstante xlAscending muss »übersetzt« werden. Auch hier zeigt die Programmiersprache die korrekte Klasse an, die hinzugefügt werden muss.
Wem die vielen Kommata zu umständlich und unübersichtlich sind, der kann die Sortiermethode auch folgendermaßen schreiben:
Sub Sortiere()
Key1:=m_xlZelle.CurrentRegion.Sort(m_xlZelle, _
Order1:=Excel.XlSortOrder.xlAscending, _
Header:=Excel.XlYesNoGuess.xlYes)
End Sub
Abbildung 8.7
Excel hilft bei langen Listen.
Hinter dem Button, der für das Anzeigen der Namen verantwortlich ist, verbirgt sich nun folgender Code:
Dim XL As clsExcel
Dim i As Integer
XL = New clsExcel()
XL.ExcelDateiName = _
DateiZugriff.ExcelDateiname(strIniDateiName)
XL.Zellzugriff("A1")
XL.Sortiere()
For i = 1 To XL.Zeilenzahl
If XL.ZellwertUnter(i) <> XL.ZellwertUnter(i + 1) Then
Me.lstListe.Items.Add(XL.ZellwertUnter(i))
End If
Next
XL.ExcelSchließen(False)
Um die Rechnungsbeträge der einzelnen Konsumenten zu ermitteln, gibt es eine Reihe von Möglichkeiten. Man könnte in Excel den Assistenten »Teilergebnisse« verwenden, man könnte nach einer Auswahl auf dem Formular nach den Daten suchen lassen oder schon gleich beim Füllen der Liste die Summe für jeden einzelnen Namen der Liste ermitteln. Ich verwende die dritte Variante. Eine globale Variable wird innerhalb der Schleife hochgezählt. Natürlich wird das Datenfeld bei jedem neuen Namen erweitert. Und eine weitere Eigenschaft wird benötigt. Die Eigenschaft lautet:
Function ZellwertBetrag(ByVal Zeilen As Integer, _
ByVal Spalten As Integer) As Decimal
Return m_xlZelle.Offset(Zeilen, Spalten).Value()
End Function
Abbildung 8.8
Nun stehen die Namen sortiert untereinander in der Liste.
Die Schleife wird nun erweitert auf:
For i = 1 To XL.Zeilenzahl
decBetrag(intZähler) += XL.ZellwertBetrag(i, 1)
If XL.ZellwertUnter(i) <> XL.ZellwertUnter(i + 1) Then
Me.lstListe.Items.Add(XL.ZellwertUnter(i))
intZähler += 1
ReDim Preserve decBetrag(intZähler)
decBetrag(intZähler) = 0
End If
Next
XL.ExcelSchließen(False)
Zur Probe kann man sich das Ergebnis in der Textzeile anzeigen lassen:
Private Sub lstListe_SelectedIndexChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs) Handles _
lstListe.SelectedIndexChanged
Me.lblName.Text = _
Me.lstListe.Items(Me.lstListe.SelectedIndex) & _
" zahlt: " & _
decBetrag(Me.lstListe.SelectedIndex).ToString("C")
End Sub
Abbildung 8.9
Die Summe(n) der Beträge werden angezeigt.
|